home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 22
/
AACD 22.iso
/
AACD
/
Resources
/
Sound
/
AHI
/
Developer
/
examples
/
Device
/
AHI-Handler
/
RCS
/
main.c,v
Wrap
Text File
|
1997-04-08
|
60KB
|
2,379 lines
head 4.2;
access;
symbols;
locks; strict;
comment @ * @;
4.2
date 97.04.09.01.55.32; author lcs; state Exp;
branches;
next 4.1;
4.1
date 97.04.02.22.46.37; author lcs; state Exp;
branches;
next 1.8;
1.8
date 97.03.27.12.11.25; author lcs; state Exp;
branches;
next 1.7;
1.7
date 97.03.26.13.32.43; author lcs; state Exp;
branches;
next 1.6;
1.6
date 97.02.01.14.10.08; author lcs; state Exp;
branches;
next 1.5;
1.5
date 97.01.29.15.44.49; author lcs; state Exp;
branches;
next 1.4;
1.4
date 97.01.24.23.20.47; author lcs; state Exp;
branches;
next 1.3;
1.3
date 97.01.23.19.55.50; author lcs; state Exp;
branches;
next 1.2;
1.2
date 97.01.21.23.56.21; author lcs; state Exp;
branches;
next 1.1;
1.1
date 97.01.17.23.34.28; author lcs; state Exp;
branches;
next ;
desc
@Handler for /dev/audio-like device using AHI
@
4.2
log
@Much improved error handling.
@
text
@/* $Id: main.c,v 4.1 1997/04/02 22:46:37 lcs Exp lcs $
* $Log: main.c,v $
* Revision 4.1 1997/04/02 22:46:37 lcs
* Bumped to version 4
*
* Revision 1.8 1997/03/27 12:11:25 lcs
* Never mind! Bah.
*
* Revision 1.7 1997/03/26 13:32:43 lcs
* Added UNIT to the template, and set taskpri to 5.
*
* Revision 1.6 1997/02/01 14:10:08 lcs
* A couple of bugs fixed.
*
* Revision 1.5 1997/01/29 15:44:49 lcs
* It's "finished"!
*
* Revision 1.4 1997/01/24 23:20:47 lcs
* Writing seem to work too...
*
* Revision 1.3 1997/01/23 19:55:50 lcs
* Added AIFF and AIFC saving.
*
* Revision 1.2 1997/01/21 23:56:21 lcs
* Reading seem to work okay now.
*
* Revision 1.1 1997/01/17 23:34:28 lcs
* Initial revision
*
*/
/*
* This code is written using DICE, and is based on the DosHan example
* source code that came with the compiler. Not all comments are mine,
* by the way...
*
* Done by Martin Blom 1997. Public Domain.
*
*/
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/ports.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/filehandler.h>
#include <dos/rdargs.h>
#include <devices/ahi.h>
#include <proto/ahi.h>
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/dos_protos.h>
#include <clib/utility_protos.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "main.h"
/*
* Prototypes
*/
LONG PlayAndSwap(struct HandlerData *, LONG);
long extended2long(extended *);
void ulong2extended (ULONG, extended *);
void FillAIFFheader(struct HandlerData *);
void FillAIFCheader(struct HandlerData *);
LONG ReadCOMMchunk(struct HandlerData *, UBYTE *, LONG);
long AllocAudio(int);
void FreeAudio(void);
long ParseArgs(struct HandlerData *, char *);
long InitHData(struct HandlerData *);
void FreeHData(struct HandlerData *);
void returnpacket (struct DosPacket *);
void Initialize (void);
void UnInitialize (void);
/*
* Some macros
*/
#define min(a,b) ((a)<=(b)?(a):(b))
#define DOS_TRUE -1
#define DOS_FALSE 0
#define BTOC(bptr) ((void *)((long)(bptr) << 2))
#define CTOB(cptr) ((BPTR)(((long)cptr) >> 2))
/*
* My debug stuff....
*/
#define HIT(x) {char *a=NULL; *a=x;}
void kprintf(char *, ...);
/*
* Global variables
*/
const static char ID[] = "$VER: AHI-Handler 4.2 (9.4.97)\r\n";
struct List HanList;
struct DeviceNode *DevNode;
struct MsgPort *PktPort;
int AllocCnt;
BOOL Running;
struct MsgPort *AHImp = NULL;
struct AHIRequest *AHIio = NULL;
BYTE AHIDevice = -1;
struct Library *AHIBase;
struct AIFCHeader AIFCHeader = {
ID_FORM, NULL, ID_AIFC,
ID_FVER, sizeof(FormatVersionHeader), {
AIFCVersion1
},
ID_COMM, sizeof(ExtCommonChunk), {
0,
0,
0,
{0},
NO_COMPRESSION,
sizeof("not compressed")-1,
'n','o','t',' ','c','o','m','p','r','e','s','s','e','d'
},
ID_SSND, NULL, {0,0}
};
struct AIFFHeader AIFFHeader = {
ID_FORM, NULL, ID_AIFF,
ID_COMM, sizeof(CommonChunk),{
0,
0,
0,
{0}
},
ID_SSND, NULL, {0,0}
};
/******************************************************************************
**** Entry ********************************************************************
******************************************************************************/
/*
* Note that we use the _main entry point. Also notice that we do not
* need to open any libraries.. they are openned for us via DICE's
* unique auto-library-open ability.
*/
void _main ()
{
struct DosPacket *packet;
struct Process *proc = (struct Process *) FindTask (NULL);
PktPort = &proc->pr_MsgPort;
NewList (&HanList);
Initialize ();
Running = TRUE;
AllocCnt = 0;
#ifdef DEBUG
kprintf("Init\n");
#endif
/*
* Main Loop
*/
while(Running) {
struct Message *msg;
while ((msg = GetMsg (PktPort)) == NULL)
Wait (1 << PktPort->mp_SigBit);
packet = (struct DosPacket *) msg->mn_Node.ln_Name;
/*
* default return value
*/
packet->dp_Res1 = DOS_TRUE;
packet->dp_Res2 = 0;
/*
* switch on packet
*/
switch (packet->dp_Type) {
case ACTION_DIE: /* ??? */
{
break;
}
/***********************************************************************/
case ACTION_FINDUPDATE: /* FileHandle,Lock,Name Bool */
case ACTION_FINDINPUT: /* FileHandle,Lock,Name Bool */
case ACTION_FINDOUTPUT: /* FileHandle,Lock,Name Bool */
{
struct FileHandle *fh = BTOC (packet->dp_Arg1);
unsigned char *base = BTOC (packet->dp_Arg3);
int len = *base;
char buf[128];
struct HandlerData *data;
int unit = AHI_DEFAULT_UNIT;
// Skip volume name and ':'
while(*++base != ':')
--len;
++base;
{
// Convert /'s to blanks
char *p = base;
while(*++p)
if(*p == '/')
*p = ' ';
}
if (len >= sizeof (buf))
len = sizeof (buf) - 1;
strncpy (buf, base, len - 1);
buf[len - 1] = '\n';
buf[len] = 0;
#ifdef DEBUG
kprintf("ACTION_FIND#?: %s\n", (char *) buf);
#endif
data = AllocVec(sizeof(struct HandlerData), MEMF_PUBLIC | MEMF_CLEAR);
if(! data) {
packet->dp_Res1 = DOS_FALSE;
packet->dp_Res2 = ERROR_NO_FREE_STORE;
break;
}
if(packet->dp_Res2 = ParseArgs(data, (char *) buf)) {
FreeHData(data);
packet->dp_Res1 = DOS_FALSE;
break;
}
if(data->args.unit) {
unit = *data->args.unit;
}
if(packet->dp_Res2 = AllocAudio(unit)) {
FreeAudio();
FreeHData(data);
packet->dp_Res1 = DOS_FALSE;
break;
}
fh->fh_Arg1 = (ULONG) data;
fh->fh_Port = (struct MsgPort *) DOS_TRUE;
break;
}
/***********************************************************************/
case ACTION_READ: /* FHArg1,CPTRBuffer,Length ActLength */
{
/*
* Reading is straightforward except for handling EOF... We
* must guarentee a return value of 0 (no bytes left) before
* beginning to return EOFs (-1's). If we return a negative
* number right off programs like COPY will assume a failure
* (if AUDIO: is the source) and delete the destination file.
*
* The basic idea is to feed the packets from one buffer while
* recording asyncroniously to the other. When we have read
* the buffer, we wait until the other is filled, and switch
* buffer pointers.
*/
struct HandlerData *data = (struct HandlerData *) packet->dp_Arg1;
UBYTE *dest = (void *) packet->dp_Arg2;
LONG length, filled;
#ifdef DEBUG
kprintf("ACTION_READ: 0x%08lx, %ld\n", packet->dp_Arg2, packet->dp_Arg3);
#endif
if(! data->initialized) {
packet->dp_Res2 = InitHData(data);
if(packet->dp_Res2) {
packet->dp_Res1 = -1;
break;
}
}
length = filled = min(data->totallength, packet->dp_Arg3);
if(length <= 0) {
packet->dp_Res1 = length;
data->totallength = -1;
break;
}
if(data->buffer1 == NULL) {
data->buffer1 = AllocVec(data->buffersize, MEMF_PUBLIC);
data->buffer2 = AllocVec(data->buffersize, MEMF_PUBLIC);
data->readreq = AllocVec(sizeof (struct AHIRequest), MEMF_PUBLIC);
if((data->buffer1 == NULL)
|| (data->buffer2 == NULL)
|| (data->readreq == NULL)) {
packet->dp_Res1 = -1;
packet->dp_Res2 = ERROR_NO_FREE_STORE;
break;
}
CopyMem(AHIio, data->readreq, sizeof (struct AHIRequest));
// Fill buffer 2
// Note that io_Offset is always 0 the first time
data->readreq->ahir_Std.io_Command = CMD_READ;
data->readreq->ahir_Std.io_Data = data->buffer2;
data->readreq->ahir_Std.io_Length = data->buffersize;
data->readreq->ahir_Std.io_Offset = 0;
data->readreq->ahir_Type = data->type;
data->readreq->ahir_Frequency = data->freq;
data->readreq->ahir_Volume = data->vol;
data->readreq->ahir_Position = data->pos;
SendIO((struct IORequest *) data->readreq);
// Force buffer switch filling of the other buffer
data->length = data->offset = 0;
// Check if we should write a header first
if(data->format == AIFF) {
if(length < sizeof(struct AIFFHeader)) {
packet->dp_Res1 = -1;
packet->dp_Res2 = ERROR_BAD_NUMBER;
break;
}
FillAIFFheader(data);
CopyMem(&AIFFHeader, dest, sizeof(struct AIFFHeader));
dest += sizeof(struct AIFFHeader);
length -= sizeof(struct AIFFHeader);
}
else if(data->format == AIFC) {
if(length < sizeof(struct AIFCHeader)) {
packet->dp_Res1 = -1;
packet->dp_Res2 = ERROR_BAD_NUMBER;
break;
}
FillAIFCheader(data);
CopyMem(&AIFCHeader, dest, sizeof(struct AIFCHeader));
dest += sizeof(struct AIFCHeader);
length -= sizeof(struct AIFCHeader);
}
}
while(length > 0) {
LONG thislength;
if(data->offset >= data->length) {
void *temp;
temp = data->buffer1;
data->buffer1 = data->buffer2;
data->buffer2 = temp;
if(WaitIO((struct IORequest *) data->readreq)) {
packet->dp_Res1 = -1;
if(data->readreq->ahir_Std.io_Error == AHIE_HALFDUPLEX) {
packet->dp_Res2 = ERROR_OBJECT_IN_USE;
}
else {
packet->dp_Res2 = ERROR_READ_PROTECTED;
}
break;
}
data->length = data->readreq->ahir_Std.io_Actual;
data->offset = 0;
data->readreq->ahir_Std.io_Command = CMD_READ;
data->readreq->ahir_Std.io_Data = data->buffer2;
data->readreq->ahir_Std.io_Length = data->buffersize;
data->readreq->ahir_Type = data->type;
data->readreq->ahir_Frequency = data->freq;
data->readreq->ahir_Volume = data->vol;
data->readreq->ahir_Position = data->pos;
SendIO((struct IORequest *) data->readreq);
} /* if */
thislength = min(data->length - data->offset, length);
CopyMem(data->buffer1 + data->offset, dest, thislength);
dest += thislength;
length -= thislength;
data->offset += thislength;
data->totallength -= thislength;
} /* while */
if(packet->dp_Res2 == 0) {
packet->dp_Res1 = filled;
}
break;
} /* ACTION_READ */
/***********************************************************************/
case ACTION_WRITE: /* FHArg1,CPTRBuffer,Length ActLength */
{
struct HandlerData *data = (struct HandlerData *) packet->dp_Arg1;
UBYTE *src = (void *) packet->dp_Arg2;
LONG length = packet->dp_Arg3, filled;
#ifdef DEBUG
kprintf("ACTION_WRITE: 0x%08lx, %ld\n", packet->dp_Arg2, packet->dp_Arg3);
#endif
if(data->buffer1 == NULL) {
// Check headers?
switch(data->args.format) {
case AIFF:
if((((ULONG *) src)[0] != ID_FORM)
|| (((ULONG *) src)[2] != ID_AIFF)) {
packet->dp_Res2 = ERROR_OBJECT_WRONG_TYPE;
}
break;
case AIFC:
if((((ULONG *) src)[0] != ID_FORM)
|| (((ULONG *) src)[2] != ID_AIFC)) {
packet->dp_Res2 = ERROR_OBJECT_WRONG_TYPE;
}
break;
case 0:
if(((ULONG *) src)[0] == ID_FORM) {
if(((ULONG *) src)[2] == ID_AIFF) {
data->args.format = AIFF;
}
else if(((ULONG *) src)[2] == ID_AIFC) {
data->args.format = AIFC;
}
}
break;
default:
break;
}
if(packet->dp_Res2) {
packet->dp_Res1 = -1;
break;
}
if((data->args.format == AIFF) || (data->args.format == AIFC)) {
LONG skiplen = 0;
skiplen = ReadCOMMchunk(data, src, length);
src += skiplen;
length -= skiplen;
}
if(packet->dp_Res2 = InitHData(data)) {
packet->dp_Res1 = -1;
break;
}
data->writing = TRUE;
data->buffer1 = AllocVec(data->buffersize, MEMF_PUBLIC);
data->buffer2 = AllocVec(data->buffersize, MEMF_PUBLIC);
if((data->buffer1 == NULL) || (data->buffer2 == NULL)) {
packet->dp_Res1 = -1;
packet->dp_Res2 = ERROR_NO_FREE_STORE;
break;
}
data->offset = 0;
data->length = (data->buffersize / AHI_SampleFrameSize(data->type))
* AHI_SampleFrameSize(data->type);
}
length = min(data->totallength, length);
filled = min(data->totallength, packet->dp_Arg3);
while(length > 0) {
LONG thislength;
if(data->offset >= data->length) {
packet->dp_Res2 = PlayAndSwap(data, data->length);
if(packet->dp_Res2) {
packet->dp_Res1 = -1;
break;
}
}
thislength = min(data->length - data->offset, length);
CopyMem(src, data->buffer1 + data->offset, thislength);
src += thislength;
length -= thislength;
data->offset += thislength;
data->totallength -= thislength;
} /* while */
if(packet->dp_Res2 == 0) {
packet->dp_Res1 = filled;
}
break;
}
/***********************************************************************/
case ACTION_END: /* FHArg1 Bool:TRUE */
{
struct HandlerData *data = (struct HandlerData *) packet->dp_Arg1;
#ifdef DEBUG
kprintf("ACTION_END\n");
#endif
// Abort any reading requests
if(data->readreq) {
AbortIO((struct IORequest *) data->readreq);
WaitIO((struct IORequest *) data->readreq);
}
// Finish any playing requests
if(data->writing) {
PlayAndSwap(data, data->offset);
if(data->writereq1) {
WaitIO((struct IORequest *) data->writereq1);
}
if(data->writereq2) {
WaitIO((struct IORequest *) data->writereq2);
}
}
FreeHData(data);
FreeAudio();
break;
}
/***********************************************************************/
case ACTION_IS_FILESYSTEM:
packet->dp_Res1 = DOS_FALSE;
break;
/***********************************************************************/
default:
packet->dp_Res1 = DOS_FALSE;
packet->dp_Res2 = ERROR_ACTION_NOT_KNOWN;
break;
} /* switch */
if(AllocCnt == 0)
Running = FALSE;
if (packet) {
returnpacket (packet);
#ifdef DEBUG
kprintf("Retured packet\n");
#endif
}
} /* for */
#ifdef DEBUG
kprintf("Dying..!\n");
#endif
UnInitialize();
_exit (0);
}
/******************************************************************************
**** PlayAndSwap **************************************************************
******************************************************************************/
/*
* Starts to play the current buffer. Handles double buffering.
*/
LONG PlayAndSwap(struct HandlerData *data, LONG length) {
void *temp;
temp = data->buffer1;
data->buffer1 = data->buffer2;
data->buffer2 = temp;
temp = data->writereq1;
data->writereq1 = data->writereq2;
data->writereq2 = temp;
if(data->writereq1 == NULL) {
data->writereq1 = AllocVec(sizeof (struct AHIRequest), MEMF_PUBLIC);
if(data->writereq1 == NULL) {
return ERROR_NO_FREE_STORE;
}
CopyMem(AHIio, data->writereq1, sizeof (struct AHIRequest));
}
data->offset = 0;
data->writereq1->ahir_Std.io_Message.mn_Node.ln_Pri = data->priority;
data->writereq1->ahir_Std.io_Command = CMD_WRITE;
data->writereq1->ahir_Std.io_Data = data->buffer2;
data->writereq1->ahir_Std.io_Length = length;
data->writereq1->ahir_Std.io_Offset = 0;
data->writereq1->ahir_Type = data->type;
data->writereq1->ahir_Frequency = data->freq;
data->writereq1->ahir_Volume = data->vol;
data->writereq1->ahir_Position = data->pos;
data->writereq1->ahir_Link = data->writereq2;
SendIO((struct IORequest *) data->writereq1);
if(data->writereq2) {
if(WaitIO((struct IORequest *) data->writereq2)) {
if(data->writereq2->ahir_Std.io_Error == AHIE_HALFDUPLEX) {
return ERROR_OBJECT_IN_USE;
}
else {
return ERROR_WRITE_PROTECTED;
}
}
}
return 0;
}
/******************************************************************************
**** extended2long ************************************************************
******************************************************************************/
/*
* This function translates Apples SANE Extended used in AIFF/AIFC files
* to a LONG. Stolen from Olaf `Olsen' Barthel's AIFF datatype.
*/
long extended2long(extended *ex)
{
unsigned long mantissa;
long exponent,sign;
// We only need 32 bits precision
mantissa = ex->mantissa[0];
// Is the mantissa positive or negative?
exponent = ex->exponent;
if(exponent & 0x8000)
sign = -1;
else
sign = 1;
// Unbias the exponent
exponent = (exponent & 0x7FFF) - 0x3FFF;
// If the exponent is negative, set the mantissa to zero
if(exponent < 0)
mantissa = 0;
else
{
// Special meaning?
exponent -= 31;
// Overflow?
if(exponent > 0)
mantissa = 0x7FFFFFFF;
else
mantissa >>= -exponent; // Let the point float...
}
// That's all...
return(sign * (long)mantissa);
}
/******************************************************************************
**** ulong2extended ***********************************************************
******************************************************************************/
/*
* This function translates an ULONG to Apples SANE Extended
* used in AIFF/AIFC files.
*/
void ulong2extended (ULONG in, extended *ex)
{
ex->exponent=31+16383;
ex->mantissa[1]=0;
while(!(in & 0x80000000))
{
ex->exponent--;
in<<=1;
}
ex->mantissa[0]=in;
}
/******************************************************************************
**** FillAIFFheader ***********************************************************
******************************************************************************/
void FillAIFFheader(struct HandlerData *data) {
AIFFHeader.FORMsize = sizeof(AIFFHeader) + data->totallength - 8;
AIFFHeader.COMMchunk.numChannels = data->channels;
AIFFHeader.COMMchunk.numSampleFrames =
data->totallength / AHI_SampleFrameSize(data->type);
AIFFHeader.COMMchunk.sampleSize = data->bits;
ulong2extended(data->freq, &AIFFHeader.COMMchunk.sampleRate);
AIFFHeader.SSNDsize = sizeof(SampledSoundHeader) + data->totallength;
}
/******************************************************************************
**** FillAIFCheader ***********************************************************
******************************************************************************/
void FillAIFCheader(struct HandlerData *data) {
AIFCHeader.FORMsize = sizeof(AIFCHeader) + data->totallength - 8;
AIFCHeader.COMMchunk.numChannels = data->channels;
AIFCHeader.COMMchunk.numSampleFrames =
data->totallength / AHI_SampleFrameSize(data->type);
AIFCHeader.COMMchunk.sampleSize = data->bits;
ulong2extended(data->freq, &AIFCHeader.COMMchunk.sampleRate);
AIFCHeader.SSNDsize = sizeof(SampledSoundHeader) + data->totallength;
}
/******************************************************************************
**** ReadCOMMchunk ************************************************************
******************************************************************************/
LONG ReadCOMMchunk(struct HandlerData *data, UBYTE *buffer, LONG length) {
UWORD *src = (UWORD *) buffer;
LONG len = (length >> 1) - 2;
ExtCommonChunk *common;
while(len > 0) {
if(((ULONG *) src)[0] == ID_COMM) {
common = (ExtCommonChunk *) (src + 4);
data->channels = common->numChannels;
data->bits = common->sampleSize;
data->totallength = common->numSampleFrames * common->numChannels *
(data->bits <= 8 ? 1 : (data->bits <= 16 ? 2 : (data->bits <= 32 ? 4 : 0)));
data->freq = extended2long(&common->sampleRate);
if(!data->args.channels)
data->args.channels = &data->channels;
if(!data->args.bits)
data->args.bits = &data->bits;
if(!data->args.length)
data->args.length = &data->totallength;
if(!data->args.freq)
data->args.freq = &data->freq;
}
else if(((ULONG *) src)[0] == ID_SSND) {
src += 8;
break;
}
src++;
len--;
}
return (LONG) src - (LONG) buffer;
}
/******************************************************************************
**** AllocAudio ***************************************************************
******************************************************************************/
/*
* If the device isn't already open, open it now
*/
long AllocAudio(int unit) {
long rc = 0;
if(++AllocCnt == 1) {
if(AHImp=CreateMsgPort()) {
if(AHIio=(struct AHIRequest *)CreateIORequest(AHImp,sizeof(struct AHIRequest))) {
AHIio->ahir_Version = 4;
AHIDevice=OpenDevice(AHINAME,unit,(struct IORequest *)AHIio,NULL);
}
}
if(AHIDevice) {
rc = ERROR_OBJECT_NOT_FOUND;
}
else {
AHIBase=(struct Library *)AHIio->ahir_Std.io_Device;
}
}
return rc;
}
/******************************************************************************
**** FreeAudio ****************************************************************
******************************************************************************/
/*
* If we're the last user, close the device now
*/
void FreeAudio(void)
{
if(--AllocCnt == 0) {
if(AHIDevice == 0)
CloseDevice((struct IORequest *)AHIio);
AHIDevice = -1;
DeleteIORequest((struct IORequest *)AHIio);
AHIio = NULL;
DeleteMsgPort(AHImp);
AHImp = NULL;
}
}
/******************************************************************************
**** ParseArgs ****************************************************************
******************************************************************************/
/*
* Fill out argument array. Returns 0 on success, else a DOS error code.
*/
long ParseArgs(struct HandlerData *data, char *initstring) {
long rc = 0;
data->rdargs = (struct RDArgs *) AllocDosObjectTags(DOS_RDARGS, TAG_DONE);
if(data->rdargs)
{
data->rdargs->RDA_Source.CS_Buffer = initstring;
data->rdargs->RDA_Source.CS_Length = strlen(initstring);
data->rdargs->RDA_Source.CS_CurChr = 0;
data->rdargs->RDA_Flags |= RDAF_NOPROMPT;
data->rdargs2 = ReadArgs(
"B=BITS/K/N,C=CHANNELS/K/N,F=FREQUENCY/K/N,T=TYPE/K,V=VOLUME/K/N,P=POSITION/K/N,"
"PRI=PRIORITY/K/N,L=LENGTH/K/N,S=SECONDS/K/N,BUF=BUFFER/K/N,UNIT/K/N",
(LONG *) &data->args, data->rdargs);
if(data->rdargs2 != NULL) {
if(! data->args.type) {
data->args.format = 0;
}
else if(Stricmp("SIGNED", data->args.type) == 0) {
data->args.format = SIGNED;
}
else if(Stricmp("AIFF", data->args.type) == 0) {
data->args.format = AIFF;
}
else if(Stricmp("AIFC", data->args.type) == 0) {
data->args.format = AIFC;
}
else {
rc = ERROR_BAD_TEMPLATE;
}
}
else
rc = ERROR_BAD_TEMPLATE;
}
else
rc = ERROR_NO_FREE_STORE;
return rc;
}
/******************************************************************************
**** InitHData ****************************************************************
******************************************************************************/
/*
* Initialize the HandlerData data structure, based on the args structure
* (see ParseArgs()). Returns 0 on success, else a DOS error code.
*/
#define S8bitmode 0
#define S16bitmode 1
#define S32bitmode 8
#define Sstereoflag 2
long InitHData(struct HandlerData *data) {
ULONG bits = 8, channels = 1, freq = 8000;
LONG volume = 100, position = 0, priority = 0,
length = MAXINT, buffersize = 32768;
long rc = 0;
data->initialized = TRUE;
// Fill in default values
if(!data->args.bits)
data->args.bits = &bits;
if(!data->args.channels)
data->args.channels = &channels;
if(!data->args.freq)
data->args.freq = &freq;
if(!data->args.volume)
data->args.volume = &volume;
if(!data->args.position)
data->args.position = &position;
if(!data->args.priority)
data->args.priority = &priority;
if(!data->args.length)
data->args.length = &length;
if(!data->args.buffersize)
data->args.buffersize = &buffersize;
if(!data->args.format)
data->args.format = SIGNED;
// 8, 16 or 32 bit
if(*data->args.bits <= 8)
data->type = S8bitmode;
else if(*data->args.bits <= 16)
data->type = S16bitmode;
else if(*data->args.bits <= 32)
data->type = S32bitmode;
else {
rc = ERROR_OBJECT_WRONG_TYPE;
goto quit;
}
// Mono or stereo
if((*data->args.channels > 2) || (*data->args.channels < 1)) {
rc = ERROR_OBJECT_WRONG_TYPE;
goto quit;
}
if(*data->args.channels == 2)
data->type |= Sstereoflag;
data->bits = *data->args.bits;
data->channels = *data->args.channels;
data->freq = *data->args.freq;
data->vol = *data->args.volume * 0x10000 / 100;
{ // Don't ask why... :(
LONG a;
a = *data->args.position * 0x8000;
a = a / 100 + 0x8000;
data->pos = a;
}
data->priority = *data->args.priority;
if(data->args.seconds) {
data->totallength = *data->args.seconds * data->freq
* AHI_SampleFrameSize(data->type);
}
else {
data->totallength = (*data->args.length / AHI_SampleFrameSize(data->type))
* AHI_SampleFrameSize(data->type);
}
data->format = data->args.format;
switch(data->format) {
case AIFF:
case AIFC:
data->totallength = data->totallength & ~1; // Make even
break;
}
data->buffersize = *data->args.buffersize;
quit:
return rc;
}
/******************************************************************************
**** FreeHData ****************************************************************
******************************************************************************/
/*
* Deallocate the HandlerData structure
*/
void FreeHData(struct HandlerData *data) {
if(data) {
if(data->rdargs2)
FreeArgs(data->rdargs2);
if(data->rdargs);
FreeDosObject(DOS_RDARGS, data->rdargs);
FreeVec(data->buffer1);
FreeVec(data->buffer2);
FreeVec(data->readreq);
FreeVec(data->writereq1);
FreeVec(data->writereq2);
FreeVec(data);
}
}
/******************************************************************************
**** returnpacket *************************************************************
******************************************************************************/
/*
* PACKET ROUTINES. Dos Packets are in a rather strange format as you
* can see by this and how the PACKET structure is extracted in the
* GetMsg() of the main routine.
*/
void returnpacket (struct DosPacket *packet) {
struct Message *mess;
struct MsgPort *replyPort;
replyPort = packet->dp_Port;
mess = packet->dp_Link;
packet->dp_Port = PktPort;
mess->mn_Node.ln_Name = (char *) packet;
PutMsg (replyPort, mess);
}
/******************************************************************************
**** Initialize ***************************************************************
******************************************************************************/
/*
* During initialization DOS sends us a packet and sets our dn_SegList
* pointer. If we set our dn_Task pointer than every Open's go to the
* same handler (this one). If we set dn_Task to NULL, every Open()
* will create a NEW instance of this process via the seglist, meaning
* our process must be reentrant (i.e. -r option).
*
* note: dn_Task points to the MESSAGE PORT portion of the process
* (or your own custom message port).
*
* If we clear the SegList then we also force DOS to reload our process
* from disk, but we also need some way of then UnLoadSeg()ing it ourselves,
* which we CANNOT do from this process since it rips our code out from
* under us.
*/
void Initialize () {
struct DeviceNode *dn;
struct Process *proc = (struct Process *) FindTask (NULL);
struct DosPacket *packet;
/*
* Handle initial message.
*/
struct Message *msg;
WaitPort (PktPort);
msg = GetMsg (PktPort);
packet = (struct DosPacket *) msg->mn_Node.ln_Name;
DevNode = dn = BTOC (packet->dp_Arg3);
dn->dn_Task = NULL;
packet->dp_Res1 = DOS_TRUE;
packet->dp_Res2 = 0;
returnpacket (packet);
}
/******************************************************************************
**** UnInitialize *************************************************************
******************************************************************************/
void UnInitialize (void) {
struct DeviceNode *dn = DevNode;
dn->dn_Task = NULL;
}
@
4.1
log
@Bumped to version 4
@
text
@d1 1
a1 1
/* $Id: main.c,v 1.8 1997/03/27 12:11:25 lcs Exp lcs $
d3 3
d71 1
a71 1
BOOL PlayAndSwap(struct HandlerData *, LONG);
d110 1
a110 1
const static char ID[] = "$VER: AHI-Handler 4.1 (2.4.97)\r\n";
d249 1
d256 1
d267 1
d306 1
d328 1
d357 1
d371 1
d394 11
a404 1
WaitIO((struct IORequest *) data->readreq);
a407 6
if(data->readreq->ahir_Std.io_Error) {
packet->dp_Res2 = ERROR_READ_PROTECTED;
length = 0;
break;
}
d426 3
a428 1
packet->dp_Res1 = filled;
d478 2
a479 1
if(packet->dp_Res2)
d481 1
d491 2
a492 1
if(packet->dp_Res2 = InitHData(data))
d494 1
d502 1
d520 2
a521 1
if(! PlayAndSwap(data, data->length)) {
a522 1
length = 0;
d536 3
a538 1
packet->dp_Res1 = filled;
d588 1
a597 2
if (packet->dp_Res2)
packet->dp_Res1 = DOS_FALSE;
d622 1
a622 1
BOOL PlayAndSwap(struct HandlerData *data, LONG length) {
d637 3
a639 2
if(data->writereq1 == NULL)
return FALSE;
d659 7
a665 4
WaitIO((struct IORequest *) data->writereq2);
if(data->writereq2->ahir_Std.io_Error) {
return FALSE;
d669 1
a669 1
return TRUE;
@
1.8
log
@Never mind! Bah.
@
text
@d1 1
a1 1
/* $Id: main.c,v 1.7 1997/03/26 13:32:43 lcs Exp lcs $
d3 3
d107 1
a107 1
const static char ID[] = "$VER: AHI-Handler 1.8 (27.3.97)\r\n";
d808 1
a808 1
AHIio->ahir_Version=3;
@
1.7
log
@Added UNIT to the template, and set taskpri to 5.
@
text
@d1 1
a1 1
/* $Id: main.c,v 1.6 1997/02/01 14:10:08 lcs Exp lcs $
d3 3
d104 1
a104 1
const static char ID[] = "$VER: AHI-Handler 1.7 (12.3.97)\r\n";
a159 4
/* Boost our priority */
SetTaskPri(FindTask(NULL), 5);
@
1.6
log
@A couple of bugs fixed.
@
text
@d1 1
a1 1
/* $Id: main.c,v 1.5 1997/01/29 15:44:49 lcs Exp lcs $
d3 3
a29 47
* Usage: Open AUDIO: for reading, or writing. Options can be given like
* this: "AUDIO:PRIORITY=1 VOLUME=50". All slashes (/) in the
* 'file' name will be translated to spaces. The removes the need
* for quotes: AUDIO:PRIORITY/1/VOLUME/50.
*
*
* The full template for reading is:
* B=BITS/K/N,C=CHANNELS/K/N,F=FREQUENCY/K/N,T=TYPE/K,
* L=LENGTH/K/N,S=SECONDS/K/N,BUF=BUFFER/K/N
*
* The full template for writing is:
* B=BITS/K/N,C=CHANNELS/K/N,F=FREQUENCY/K/N,T=TYPE/K,
* V=VOLUME/K/N,P=POSITION/K/N,PRI=PRIORITY/K/N,L=LENGTH/K/N,
* S=SECONDS/K/N,BUF=BUFFER/K/N"
*
*
* BITS can be one of 8, 16 or 32. CHANNELS can be either 1 or 2.
* The FREQUENCY is in Herz, TYPE is one of SIGNED, AIFF or AIFC.
* VOLUME ranges from 0 (silence) to 100 (full volume), and POSITION
* ranges from -100 (far left) via 0 (center) to 100 (far right).
* The PRIORITY is only used when writing, and can be from -128 to
* 127 (unstoppable). LENGTH is how many bytes you wish to read or
* write, and SECONDS is the same, but in seconds instead of bytes.
* The BUFFER size is specified in bytes. Note that two buffers are
* always used, which means that the memory usage will be 2×BUFFER.
*
*
* The default options for reading:
* BITS=8 CHANNELS=1 FREQUENCY=8000 TYPE=SIGNED LENGTH=very-very-much
* BUFFER=32768.
*
* The default options for reading:
* BITS=8 CHANNELS=1 FREQUENCY=8000 TYPE=<none> VOLUME=100 POSITION=0
* PRIORITY=0 LENGTH=very-very-much BUFFER=32768.
*
* If TYPE is not specified, the default behavour is to identify the
* data stream as IFF-AIFF or IFF-AIFC. If so, the default values of
* BITS, CHANNELS, FREQUENCY and LENGTH will be changed. You can still
* override them if you wish. If the stream could not be identified,
* the data format is assumed to be SIGNED.
*
*
* Both when reading and writing the sample rate will be converted
* on the fly to what the underlying hardware is configured to.
* Normally this is not a big problem when writing, but the quality
* when reading leaves quite a lot to wish for, since no low-pass
* filters are used.
d68 1
a68 1
long AllocAudio(void);
d101 1
a101 1
const static char ID[] = "$VER: AHI-Handler 1.6 (1.2.96)\r\n";
d158 3
d213 1
d253 5
a257 1
if(packet->dp_Res2 = AllocAudio()) {
d800 1
a800 1
long AllocAudio(void) {
d807 1
a807 1
AHIDevice=OpenDevice(AHINAME,0,(struct IORequest *)AHIio,NULL);
d833 1
a833 1
if(!AHIDevice)
d865 1
a865 1
"PRI=PRIORITY/K/N,L=LENGTH/K/N,S=SECONDS/K/N,BUF=BUFFER/K/N",
@
1.5
log
@It's "finished"!
@
text
@d1 1
a1 1
/* $Id: main.c,v 1.4 1997/01/24 23:20:47 lcs Exp lcs $
d3 3
d145 1
a145 1
const static char ID[] = "$VER: AHI-Handler 1.5 (29.1.96)\r\n";
d423 1
a423 1
packet->dp_Res1 = -1;
d805 1
a805 2
/*
data->totallength = common->numSampleFrames *
a806 1
*/
a812 1
/*
a814 1
*/
a912 3
else if(Stricmp("UNSIGNED", data->args.type) == 0) {
data->args.format = UNSIGNED;
}
a947 1
#define Sunsignedflag 4
d950 3
a952 2
ULONG bits = 8, channels = 1, freq = 8000, volume = 100, position = 0;
LONG priority = 0, length = MAXINT, buffersize = 32768;
d1006 6
a1011 1
data->pos = *data->args.position * 0x8000 / 100 + 0x8000;
d1013 1
a1025 3
case UNSIGNED:
data->type |= Sunsignedflag;
break;
@
1.4
log
@Writing seem to work too...
@
text
@d1 1
a1 1
/* $Id: main.c,v 1.3 1997/01/23 19:55:50 lcs Exp lcs $
d3 3
d23 48
d103 2
d106 3
d111 2
a112 1
long InitHData(struct HandlerData *, char *);
d142 2
d184 4
d207 1
d209 1
a236 3
kprintf("Die!\n");
if(AllocCnt == 0)
Running = FALSE;
d240 2
d275 1
d277 12
d292 1
a295 1
data = AllocVec(sizeof(struct HandlerData), MEMF_PUBLIC | MEMF_CLEAR);
d297 2
a298 9
if(packet->dp_Res2 = InitHData(data, (char *) buf)) {
FreeHData(data);
data = NULL;
FreeAudio();
}
else {
fh->fh_Arg1 = (ULONG) data;
fh->fh_Port = (struct MsgPort *) DOS_TRUE;
}
d302 2
d324 1
d326 8
d383 1
a383 8
AIFFHeader.FORMsize = sizeof(AIFFHeader) + data->totallength - 8;
AIFFHeader.COMMchunk.numChannels = data->channels;
AIFFHeader.COMMchunk.numSampleFrames =
data->totallength / AHI_SampleFrameSize(data->type);
AIFFHeader.COMMchunk.sampleSize = data->bits;
ulong2extended(data->freq, &AIFFHeader.COMMchunk.sampleRate);
AIFFHeader.SSNDsize =
sizeof(SampledSoundHeader) + data->totallength;
d396 1
a396 8
AIFCHeader.FORMsize = sizeof(AIFCHeader) + data->totallength - 8;
AIFCHeader.COMMchunk.numChannels = data->channels;
AIFCHeader.COMMchunk.numSampleFrames =
data->totallength / AHI_SampleFrameSize(data->type);
AIFCHeader.COMMchunk.sampleSize = data->bits;
ulong2extended(data->freq, &AIFCHeader.COMMchunk.sampleRate);
AIFCHeader.SSNDsize =
sizeof(SampledSoundHeader) + data->totallength;
d448 2
d454 16
a469 1
long length, filled;
d471 6
d478 25
a502 1
kprintf("ACTION_WRITE: 0x%08lx, %ld\n", packet->dp_Arg2, packet->dp_Arg3);
d504 2
a505 1
length = filled = min(data->totallength, packet->dp_Arg3);
d507 1
a507 1
if(data->buffer1 == NULL) {
d520 1
a520 1
kprintf("length: %ld\n", data->length);
d523 2
d530 4
a533 21
void *temp;
temp = data->buffer1;
data->buffer1 = data->buffer2;
data->buffer2 = temp;
temp = data->writereq1;
data->writereq1 = data->writereq2;
data->writereq2 = temp;
if(data->writereq1) {
kprintf("Väntar på 0x%08lx..\n",data->writereq1);
WaitIO((struct IORequest *) data->writereq1);
if(data->writereq1->ahir_Std.io_Error) {
packet->dp_Res1 = -1;
length = 0;
break;
}
d535 1
a535 26
else {
data->writereq1 = AllocVec(sizeof (struct AHIRequest), MEMF_PUBLIC);
if(data->writereq1 == NULL) {
packet->dp_Res1 = -1;
length = 0;
break;
}
CopyMem(AHIio, data->writereq1, sizeof (struct AHIRequest));
}
data->offset = 0;
kprintf("Spelar 0x%08lx, länkad till 0x%08lx..\n", data->writereq1, data->writereq2);
data->writereq1->ahir_Std.io_Message.mn_Node.ln_Pri = 0;
data->writereq1->ahir_Std.io_Command = CMD_WRITE;
data->writereq1->ahir_Std.io_Data = data->buffer2;
data->writereq1->ahir_Std.io_Length = data->buffersize;
data->writereq1->ahir_Std.io_Offset = 0;
data->writereq1->ahir_Type = data->type;
data->writereq1->ahir_Frequency = data->freq;
data->writereq1->ahir_Volume = data->vol;
data->writereq1->ahir_Position = data->pos;
data->writereq1->ahir_Link = data->writereq2;
SendIO((struct IORequest *) data->writereq1);
} /* if */
a537 1
kprintf("Kopierar %ld bytes..\n", thislength);
d543 1
d550 2
d556 1
d558 4
d566 12
a577 7
if(data->writereq1) {
AbortIO((struct IORequest *) data->writereq1);
WaitIO((struct IORequest *) data->writereq1);
}
if(data->writereq2) {
AbortIO((struct IORequest *) data->writereq2);
WaitIO((struct IORequest *) data->writereq2);
a582 2
if(AllocCnt == 0)
Running = FALSE;
d587 8
a595 4
{
if(AllocCnt == 0)
Running = FALSE;
kprintf("Unknow packet!\n");
a597 1
}
d601 3
d608 3
d615 1
d617 1
d623 115
d755 78
d859 4
d881 4
d886 1
a886 1
* Initialize the HandlerData data structure, parse the arguments
d889 2
a890 1
long InitHData(struct HandlerData *data, char *initstring)
d892 7
a898 1
// Returns 0 on success, else an error code
d900 4
a903 20
{
struct RDArgs *rdargs, *rdargs2;
ULONG bits = 8, channels = 1, rate = 8000, volume = 100, position = 0;
LONG length = MAXINT, buffersize = 32768;
STRPTR type = "SIGNED";
BOOL rc = 0;
struct {
ULONG *bits;
ULONG *channels;
ULONG *rate;
STRPTR type;
Fixed *volume;
sposition *position;
ULONG *length;
ULONG *seconds;
ULONG *buffersize;
} args = {
&bits, &channels, &rate, type, &volume, &position, &length, NULL, &buffersize
};
d905 1
a905 2
if(data == NULL)
return ERROR_NO_FREE_STORE;
d908 18
a925 20
rdargs = (struct RDArgs *) AllocDosObjectTags(DOS_RDARGS, TAG_DONE);
if(rdargs)
{
rdargs->RDA_Source.CS_Buffer = initstring;
rdargs->RDA_Source.CS_Length = strlen(initstring);
rdargs->RDA_Source.CS_CurChr = 0;
rdargs->RDA_Flags |= RDAF_NOPROMPT;
rdargs2 = ReadArgs(
"B=BITS/K/N,C=CHANNELS/K/N,R=RATE/K/N,T=TYPE/K,V=VOLUME/K/N,P=POSITION/K/N,"
"L=LENGTH/K/N,S=SECONDS/K/N,BUF=BUFFER/K/N",
(LONG *) &args, rdargs);
if(rdargs2 != NULL) {
kprintf("%ld bits, %ld channels, %ld Hz, %s, %ld%% volume, position %ld%%, "
"%ld bytes total, %ld seconds, %ld bytes buffer\n",
*args.bits, *args.channels, *args.rate, args.type, *args.volume, *args.position,
*args.length, (args.seconds ? *args.seconds : 0), *args.buffersize);
FreeArgs(rdargs2);
a929 1
FreeDosObject(DOS_RDARGS, rdargs);
d932 4
a935 1
rc = ERROR_OBJECT_WRONG_TYPE;
d938 8
a945 1
if(rc == 0) {
d954 71
a1024 25
// 8, 16 or 32 bit
if(*args.bits <= 8)
data->type = S8bitmode;
else if(*args.bits <= 16)
data->type = S16bitmode;
else if(*args.bits <= 32)
data->type = S32bitmode;
else
rc = ERROR_OBJECT_WRONG_TYPE;
// Mono or stereo
if(*args.channels == 2)
data->type |= Sstereoflag;
else if(*args.channels != 1)
rc = ERROR_OBJECT_WRONG_TYPE;
// Signed, unsigned, aiff, aifc...
if(Stricmp("SIGNED", args.type) == 0) {
data->format = RAW;
kprintf("Signed\n");
}
else if(Stricmp("UNSIGNED", args.type) == 0) {
d1026 5
a1030 39
data->format = RAW;
kprintf("Unsigned\n");
}
else if(Stricmp("AIFF", args.type) == 0) {
data->format = AIFF;
kprintf("AIFF\n");
}
else if(Stricmp("AIFC", args.type) == 0) {
data->format = AIFC;
kprintf("AIFC\n");
}
else {
rc = ERROR_OBJECT_WRONG_TYPE;
}
data->bits = *args.bits;
data->channels = *args.channels;
data->freq = *args.rate;
data->vol = *args.volume * 0x10000 / 100;
data->pos = *args.position * 0x8000 / 100 + 0x8000;
if(args.seconds)
data->totallength = *args.seconds * data->freq
* AHI_SampleFrameSize(data->type);
else
data->totallength = (*args.length / AHI_SampleFrameSize(data->type))
* AHI_SampleFrameSize(data->type);
switch(data->format) {
case AIFF:
case AIFC:
data->totallength = (data->totallength + 1) & ~1; // Make even
break;
default:
break;
}
// User doesn't know about double buffering!
data->buffersize = *args.buffersize >> 1;
d1033 3
d1040 13
d1057 14
a1070 8
void FreeHData(struct HandlerData *data)
{
FreeVec(data->buffer1);
FreeVec(data->buffer2);
FreeVec(data->readreq);
FreeVec(data->writereq1);
FreeVec(data->writereq2);
FreeVec(data);
d1074 4
d1084 1
a1084 3
void
returnpacket (struct DosPacket *packet)
{
d1095 5
a1131 3
/*
dn->dn_Task = PktPort;
*/
d1139 5
a1147 1
/* dn->dn_SegList = NULL; */
@
1.3
log
@Added AIFF and AIFC saving.
@
text
@d1 1
a1 1
/* $Id: main.c,v 1.2 1997/01/21 23:56:21 lcs Exp lcs $
d3 3
d15 6
a20 3
** This code is written using DICE, just for testing, and is based on the
** DosHan example source code.
*/
d45 1
a45 1
#include "aifc.h"
d48 3
a50 6
#define min(a,b) ((a)<=(b)?(a):(b))
#define DOS_TRUE -1
#define DOS_FALSE 0
#define BTOC(bptr) ((void *)((long)(bptr) << 2))
#define CTOB(cptr) ((BPTR)(((long)cptr) >> 2))
d61 16
a79 52
#define RAW 0
#define AIFF 1
#define AIFC 2
struct HandlerData {
UBYTE *buffer1; // Address of read buffer
UBYTE *buffer2;
LONG length; // Offset to first invalid sample frame
LONG offset; // Current pointer
struct AHIRequest *req;
UWORD bits;
UWORD channels;
ULONG type;
ULONG freq;
Fixed vol;
sposition pos;
LONG totallength; // Total number of bytes to play/record
LONG buffersize; // Play/record buffer size
UBYTE format;
};
struct AIFCHeader {
ULONG FORMid;
ULONG FORMsize;
ULONG AIFCid;
ULONG FVERid;
ULONG FVERsize;
FormatVersionHeader FVERchunk;
ULONG COMMid;
ULONG COMMsize;
ExtCommonChunk COMMchunk;
ULONG SSNDid;
ULONG SSNDsize;
SampledSoundHeader SSNDchunk;
};
struct AIFFHeader {
ULONG FORMid;
ULONG FORMsize;
ULONG AIFFid;
ULONG COMMid;
ULONG COMMsize;
CommonChunk COMMchunk;
ULONG SSNDid;
ULONG SSNDsize;
SampledSoundHeader SSNDchunk;
};
d81 3
d124 1
d266 1
d268 4
a271 2
if((data->buffer1 == NULL) || (data->buffer2 == NULL)) {
packet->dp_Res1 = -1;
d275 2
d280 9
a288 9
data->req->ahir_Std.io_Command = CMD_READ;
data->req->ahir_Std.io_Data = data->buffer2;
data->req->ahir_Std.io_Length = data->buffersize;
data->req->ahir_Std.io_Offset = 0;
data->req->ahir_Type = data->type;
data->req->ahir_Frequency = data->freq;
data->req->ahir_Volume = data->vol;
data->req->ahir_Position = data->pos;
SendIO((struct IORequest *) data->req);
d348 2
a349 2
WaitIO((struct IORequest *) data->req);
data->length = data->req->ahir_Std.io_Actual;
d352 1
a352 1
if(data->req->ahir_Std.io_Error) {
d358 8
a365 8
data->req->ahir_Std.io_Command = CMD_READ;
data->req->ahir_Std.io_Data = data->buffer2;
data->req->ahir_Std.io_Length = data->buffersize;
data->req->ahir_Type = data->type;
data->req->ahir_Frequency = data->freq;
data->req->ahir_Volume = data->vol;
data->req->ahir_Position = data->pos;
SendIO((struct IORequest *) data->req);
d384 7
a390 1
long bytes = packet->dp_Arg3;
d392 4
a395 1
packet->dp_Res1 = -1;
d397 1
a397 12
kprintf("ACTION_WRITE: 0x%08lx, %ld\n", packet->dp_Arg2, bytes);
#if 0
if (xn = AllocMem (sizeof (XNode), MEMF_PUBLIC | MEMF_CLEAR)) {
if (xn->xn_Buf = AllocMem (bytes, MEMF_PUBLIC)) {
movmem ((char *) packet->dp_Arg2, xn->xn_Buf, bytes);
xn->xn_Length = bytes;
packet->dp_Res1 = bytes;
AddTail (&xh->xh_List, &xn->xn_Node);
xh->xh_Flags &= ~XHF_EOF;
}
else {
FreeMem (xn, sizeof (XNode));
d399 1
d401 5
d407 65
a471 4
else {
packet->dp_Res2 = ERROR_NO_FREE_STORE;
}
#endif
d480 12
a491 2
AbortIO((struct IORequest *) data->req);
WaitIO((struct IORequest *) data->req);
d504 3
d522 1
a522 1
UnInitialize ();
d634 5
a638 4
kprintf("%ld bits, %ld channels, %ld Hz, %s, %ld%% volume, position %ld%%, "
"%ld bytes total, %ld seconds, %ld bytes buffer\n",
*args.bits, *args.channels, *args.rate, args.type, *args.volume, *args.position,
*args.length, (args.seconds ? *args.seconds : 0), *args.buffersize);
d640 1
a640 2
if(data->req = AllocVec(sizeof (struct AHIRequest), MEMF_PUBLIC) ) {
CopyMem(AHIio, data->req, sizeof (struct AHIRequest));
d643 1
a643 1
rc = ERROR_NO_FREE_STORE;
a644 1
FreeArgs(rdargs2);
d650 3
d660 65
a724 36
// 8, 16 or 32 bit
if(*args.bits <= 8)
data->type = S8bitmode;
else if(*args.bits <= 16)
data->type = S16bitmode;
else if(*args.bits <= 32)
data->type = S32bitmode;
else
rc = ERROR_OBJECT_WRONG_TYPE;
// Mono or stereo
if(*args.channels == 2)
data->type |= Sstereoflag;
else if(*args.channels != 1)
rc = ERROR_OBJECT_WRONG_TYPE;
// Signed, unsigned, aiff, aifc...
if(Stricmp("SIGNED", args.type) == 0) {
data->format = RAW;
kprintf("Signed\n");
}
else if(Stricmp("UNSIGNED", args.type) == 0) {
data->type |= Sunsignedflag;
data->format = RAW;
kprintf("Unsigned\n");
}
else if(Stricmp("AIFF", args.type) == 0) {
data->format = AIFF;
kprintf("AIFF\n");
}
else if(Stricmp("AIFC", args.type) == 0) {
data->format = AIFC;
kprintf("AIFC\n");
a725 26
else {
rc = ERROR_OBJECT_WRONG_TYPE;
}
data->bits = *args.bits;
data->channels = *args.channels;
data->freq = *args.rate;
data->vol = *args.volume * 0x10000 / 100;
data->pos = *args.position * 0x8000 / 100 + 0x8000;
if(args.seconds)
data->totallength = *args.seconds * data->freq
* AHI_SampleFrameSize(data->type);
else
data->totallength = (*args.length / AHI_SampleFrameSize(data->type))
* AHI_SampleFrameSize(data->type);
switch(data->format) {
case AIFF:
case AIFC:
data->totallength = (data->totallength + 1) & ~1; // Make even
break;
default:
break;
}
// User doesn't know about double buffering!
a726 1
data->buffersize = *args.buffersize >> 1;
d739 3
a741 1
FreeVec(data->req);
@
1.2
log
@Reading seem to work okay now.
@
text
@d1 1
a1 1
/* $Id: main.c,v 1.1 1997/01/17 23:34:28 lcs Exp lcs $
d3 3
a15 1
#define min(a,b) ((a)<=(b)?(a):(b))
a33 1
d39 4
d45 12
d61 3
a63 3
#define BTOC(bptr) ((void *)((long)(bptr) << 2))
#define CTOB(cptr) ((BPTR)(((long)cptr) >> 2))
d71 2
d79 1
d82 31
a112 4
long AllocAudio(void);
void FreeAudio(void);
long InitHData(struct HandlerData *, char *);
void FreeHData(struct HandlerData *);
a113 3
void returnpacket (struct DosPacket *);
void Initialize (void);
void UnInitialize (void);
d124 29
d218 1
d221 4
a224 1
base++;
a225 1
{ // Convert /'s to blanks
d227 1
a245 1
d273 1
a273 1
* the buffer, we wait until the other is filed, and switch
d292 1
d303 1
d315 1
d317 42
d444 4
d474 17
d508 3
d605 1
d616 1
d622 7
a628 2
// Signed or unsigned
if(Stricmp("UNSIGNED", args.type) == 0)
d630 12
a641 1
else if(Stricmp("SIGNED", args.type) != 0)
a642 10
data->freq = *args.rate;
data->vol = *args.volume * 0x10000 / 100;
data->pos = *args.position * 0x8000 / 100 + 0x8000;
if(data->vol > 0x10000) {
data->vol = 0x10000;
}
if(data->pos > 0x10000) {
data->pos = 0x10000;
d645 5
d651 2
a652 1
data->totallength = *args.seconds * data->freq;
d654 11
a664 1
data->totallength = *args.length;
d667 1
d737 1
d739 2
@
1.1
log
@Initial revision
@
text
@d1 5
a5 2
/* $Id$
* $Log$
d8 7
d22 4
d29 3
a31 1
#include <lists.h>
d41 3
a46 25
typedef struct DosPacket DosPacket;
typedef struct FileHandle FileHandle;
typedef struct DeviceNode DeviceNode;
typedef struct Process Process;
typedef struct Node Node;
typedef struct List List;
typedef struct MsgPort MsgPort;
typedef struct Message Message;
typedef struct XHandle {
Node xh_Node;
long xh_XHLen;
long xh_Refs;
long xh_Flags;
List xh_List;
} XHandle;
#define XHF_EOF 0x0001
typedef struct XNode {
Node xn_Node;
char *xn_Buf;
long xn_Offset;
long xn_Length;
} XNode;
d48 20
a67 1
void returnpacket (DosPacket *);
d71 9
a79 4
List HanList;
DeviceNode *DevNode;
MsgPort *PktPort;
d89 5
a93 5
DosPacket *packet;
{
Process *proc = (struct Process *) FindTask (NULL);
PktPort = &proc->pr_MsgPort;
}
d97 5
d106 21
a126 2
for (;;)
{
d128 30
a157 1
Message *msg;
d159 24
a182 3
while ((msg = GetMsg (PktPort)) == NULL)
Wait (1 << PktPort->mp_SigBit);
packet = (DosPacket *) msg->mn_Node.ln_Name;
d185 27
a211 14
/*
* default return value
*/
packet->dp_Res1 = DOS_TRUE;
packet->dp_Res2 = 0;
/*
* switch on packet
*/
switch (packet->dp_Type)
{
case ACTION_DIE: /* ??? */
d213 46
a258 28
case ACTION_FINDUPDATE: /* FileHandle,Lock,Name Bool */
case ACTION_FINDINPUT: /* FileHandle,Lock,Name Bool */
case ACTION_FINDOUTPUT: /* FileHandle,Lock,Name Bool */
{
FileHandle *fh = BTOC (packet->dp_Arg1);
XHandle *xh;
{
unsigned char *base = BTOC (packet->dp_Arg3);
int len = *base;
char buf[128];
if (len >= sizeof (buf))
len = sizeof (buf) - 1;
strncpy (buf, base + 1, len);
buf[len] = 0;
if ((xh = (XHandle *) FindName (&HanList, buf)) == NULL)
{
xh = AllocMem (sizeof (XHandle) + len + 1, MEMF_PUBLIC | MEMF_CLEAR);
xh->xh_XHLen = sizeof (XHandle) + len + 1;
xh->xh_Node.ln_Name = (char *) (xh + 1);
movmem (buf, xh->xh_Node.ln_Name, len + 1);
NewList (&xh->xh_List);
AddTail (&HanList, &xh->xh_Node);
}
++xh->xh_Refs;
a259 54
fh->fh_Arg1 = (ULONG) xh;
fh->fh_Port = (MsgPort *) DOS_TRUE;
}
break;
case ACTION_READ: /* FHArg1,CPTRBuffer,Length ActLength */
/*
* reading is straightforward except for handling EOF ... we
* must guarentee a return value of 0 (no bytes left) before
* beginning to return EOFs (-1's). If we return a negative
* number right off programs like COPY will assume a failure
* (if TEST: is the source) and delete the destination file
*/
{
XHandle *xh = (XHandle *) packet->dp_Arg1;
long bytes;
packet->dp_Res1 = 0;
while ((bytes = packet->dp_Arg3 - packet->dp_Res1) > 0)
{
XNode *xn = (XNode *) RemHead (&xh->xh_List);
if (xn == NULL)
break;
if (bytes > xn->xn_Length - xn->xn_Offset)
bytes = xn->xn_Length - xn->xn_Offset;
movmem (xn->xn_Buf + xn->xn_Offset, (char *) packet->dp_Arg2 + packet->dp_Res1, bytes);
xn->xn_Offset += bytes;
packet->dp_Res1 += bytes;
if (xn->xn_Offset == xn->xn_Length)
{
FreeMem (xn->xn_Buf, xn->xn_Length);
FreeMem (xn, sizeof (XNode));
}
else
{
AddHead (&xh->xh_List, &xn->xn_Node);
}
}
if (packet->dp_Res1 == 0 && GetHead (&xh->xh_List) == NULL)
{
if (xh->xh_Flags & XHF_EOF)
packet->dp_Res1 = -1; /* EOF */
xh->xh_Flags |= XHF_EOF;
}
}
break;
case ACTION_WRITE: /* FHArg1,CPTRBuffer,Length ActLength */
{
XHandle *xh = (XHandle *) packet->dp_Arg1;
XNode *xn;
long bytes = packet->dp_Arg3;
d261 39
a299 21
packet->dp_Res1 = -1;
if (xn = AllocMem (sizeof (XNode), MEMF_PUBLIC | MEMF_CLEAR))
{
if (xn->xn_Buf = AllocMem (bytes, MEMF_PUBLIC))
{
movmem ((char *) packet->dp_Arg2, xn->xn_Buf, bytes);
xn->xn_Length = bytes;
packet->dp_Res1 = bytes;
AddTail (&xh->xh_List, &xn->xn_Node);
xh->xh_Flags &= ~XHF_EOF;
}
else
{
FreeMem (xn, sizeof (XNode));
packet->dp_Res2 = ERROR_NO_FREE_STORE;
}
}
else
{
packet->dp_Res2 = ERROR_NO_FREE_STORE;
}
d301 3
a303 11
break;
case ACTION_END: /* FHArg1 Bool:TRUE */
{
XHandle *xh = (XHandle *) packet->dp_Arg1;
if (--xh->xh_Refs == 0 && GetHead (&xh->xh_List) == NULL)
{
Remove (&xh->xh_Node);
FreeMem (xh, xh->xh_XHLen);
}
break;
a304 4
break;
default:
packet->dp_Res2 = ERROR_ACTION_NOT_KNOWN;
break;
d306 2
a307 5
if (packet)
{
if (packet->dp_Res2)
packet->dp_Res1 = DOS_FALSE;
returnpacket (packet);
d309 29
d340 1
a340 3
/*
* no reached
*/
d342 1
d349 168
d523 1
a523 2
returnpacket (packet)
DosPacket *packet;
d525 2
a526 2
Message *mess;
MsgPort *replyPort;
d551 4
a554 6
void
Initialize ()
{
DeviceNode *dn;
Process *proc = (Process *) FindTask (NULL);
DosPacket *packet;
d559 2
d562 3
a564 7
{
Message *msg;
WaitPort (PktPort);
msg = GetMsg (PktPort);
packet = (DosPacket *) msg->mn_Node.ln_Name;
}
d566 2
a567 2
{
DevNode = dn = BTOC (packet->dp_Arg3);
a568 2
dn->dn_Task = PktPort;
}
d574 2
a575 5
void
UnInitialize (void)
{
{
DeviceNode *dn = DevNode;
d577 2
a578 3
dn->dn_Task = NULL;
/* dn->dn_SegList = NULL; */
}
@